package com.example.design.ddd.practice.domain.orgmng.factory;

import com.example.design.ddd.practice.domain.common.validator.CommonValidator;
import com.example.design.ddd.practice.domain.orgmng.entity.Org;
import com.example.design.ddd.practice.domain.orgmng.entity.OrgType;
import com.example.design.ddd.practice.domain.orgmng.orgservice.OrgLeaderValidator;
import com.example.design.ddd.practice.domain.orgmng.orgservice.OrgNameValidator;
import com.example.design.ddd.practice.domain.orgmng.orgservice.OrgTypeValidator;
import com.example.design.ddd.practice.domain.orgmng.orgservice.SuperiorValidator;

import java.time.LocalDateTime;

/**
 * @Description
 * @Author liuzhihui
 * @Date 2024/6/3
 */
public class OrgBuilder {
    // 用到的 validator
    private final CommonValidator commonValidator;
    private final OrgTypeValidator orgTypeValidator;
    private final SuperiorValidator superiorValidator;
    private final OrgNameValidator orgNameValidator;
    private final OrgLeaderValidator orgLeaderValidator;

    // 用这些属性保存创建对象用到的参数
    private Long tenantId;
    private Long superiorId;
    private String orgTypeCode;
    private Long leaderId;
    private String name;
    private Long createdBy;

    public OrgBuilder(CommonValidator commonValidator, OrgTypeValidator orgTypeValidator, SuperiorValidator superiorValidator, OrgNameValidator orgNameValidator, OrgLeaderValidator orgLeaderValidator) {
        this.commonValidator = commonValidator;
        this.orgTypeValidator = orgTypeValidator;
        this.superiorValidator = superiorValidator;
        this.orgNameValidator = orgNameValidator;
        this.orgLeaderValidator = orgLeaderValidator;
    }

    // 为builder 的 tenant 属性赋值，然后返回自己，以便实现链式调用
    public OrgBuilder tenantId(Long tenantId) {
        this.tenantId = tenantId;
        return this;
    }

    public OrgBuilder superiorId(Long superiorId) {
        this.superiorId = superiorId;
        return this;
    }

    public OrgBuilder orgTypeCode(String orgTypeCode) {
        this.orgTypeCode = orgTypeCode;
        return this;
    }

    public OrgBuilder leaderId(Long leaderId) {
        this.leaderId = leaderId;
        return this;
    }

    public OrgBuilder name(String name) {
        this.name = name;
        return this;
    }

    public OrgBuilder createdBy(Long createdBy) {
        this.createdBy = createdBy;
        return this;
    }

    public Org build() {
        validate();
        Org org = new Org(tenantId, orgTypeCode, LocalDateTime.now(), createdBy);
        org.setLeaderId(this.leaderId);
        org.setName(this.name);
        org.setSuperiorId(this.superiorId);
        return org;
    }

    private void validate() {
        validateOrgTenant();
        validateOrgLeader();
        validateOrgType();
        validateSuperior();
        validateOrgName();
    }
    private void validateOrgName() {
        orgNameValidator.orgNameShouldNotEmpty(name);
        orgNameValidator.nameShouldNotDuplicatedInSameSuperior(tenantId, superiorId, name);
    }
    private void validateOrgType() {
        orgTypeValidator.shouldNotEmpty(orgTypeCode);
        orgTypeValidator.shouldEffective(tenantId, orgTypeCode);
        orgTypeValidator.shouldNotEntp(orgTypeCode);
    }

    private void validateOrgTenant() {
        commonValidator.tenantShouldValid(tenantId);
    }

    private void validateOrgLeader() {
        orgLeaderValidator.leaderShouldBeEffective(tenantId, leaderId);
    }

    private void validateSuperior() {
        Org superiorOrg = superiorValidator.shouldEffective(tenantId, superiorId);
        OrgType superiorOrgType = superiorValidator.orgTypeShouldEffective(tenantId, superiorId, superiorOrg);
        superiorValidator.ofDevGroupMustDevCenter(superiorId, orgTypeCode, superiorOrgType);
        superiorValidator.ofDevCenterAndDirectDeptMustEntp(superiorId, orgTypeCode, superiorOrgType);
    }
}
